package znet

import (
	"fmt"
	"github.com/ShiYY/zinx/ziface"
	"github.com/ShiYY/zinx/zutils"
	"net"
)

// IServer的接口实现, 定义一个Server的服务器模块
type Server struct {
	// 服务器名称
	Name string
	// 服务器绑定的IP版本
	IPVersion string
	// 服务器监听的IP
	IP string
	// 服务器监听的端口
	Port int
	// 当前Server添加一个router, server注册的链接对应的处理业务
	Router ziface.IRouter
}

// 定义当前客户端链接所绑定的handler api (目前这个handler是写死的, 以后优化应该由开发者自定义handler方法)
//func CallBackToClient(conn *net.TCPConn, data []byte, len int) error {
//	// 回显的业务
//	fmt.Println("[Conn Handler] CallbackToClient...")
//	if _, err := conn.Write(data[:len]); err != nil {
//		fmt.Println("write back buf err ", err)
//		return errors.New("CallBackToClient error")
//	}
//
//	return nil
//}

// 启动服务器
func (s *Server) Start() {
	fmt.Printf("[zinx] server name : %s, listener at ip : %s, port : %d is running\n",
		zutils.GlobalObject.Name, zutils.GlobalObject.Host, zutils.GlobalObject.TcpPort)
	fmt.Printf("[zinx info] version : %s, maxConn : %d, maxPackageSize : %d\n",
		zutils.GlobalObject.Version, zutils.GlobalObject.MaxConn, zutils.GlobalObject.MaxPackageSize)
	// fmt.Printf("[Start] Server Listener at IP : %s, Port : %d, is runnging\n", s.IP, s.Port)

	// ? 防止阻塞
	go func() {
		// 1. 获取一个TCP的Addr
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			fmt.Println("resolve tcp addr error : ", err)
			return
		}

		// 2. 监听服务器的地址
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen : ", s.IPVersion, "err : ", err)
			return
		}

		fmt.Println("start zinx server successful, ", s.Name)

		var cid uint32
		cid = 0
		// 3. 阻塞的等待客户端连接, 处理客户端连接业务(读写)
		for {
			// 如果客户端连接过来, 阻塞会返回
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("Accept err, ", err)
				continue
			}

			// 将处理新链接的业务方法 和 conn 进行绑定 得到我们封装的链接模块
			// dealConn := NewConnection(conn, cid, CallBackToClient)
			dealConn := NewConnection(conn, cid, s.Router)
			cid ++

			// 启动当前的链接业务处理
			dealConn.Start()

			// 已经与客户端建立连接, 做一些业务, 做一个最基本的最大512字节长度的回显业务
			//go func() {
			//	for {
			//		buf := make([]byte, 512)
			//		len, err := conn.Read(buf)
			//		if err != nil {
			//			fmt.Println("rev buf err, ", err)
			//			continue
			//		}
			//
			//		fmt.Printf("recv client buf %s, len %d\n", buf, len)
			//
			//		// 回显功能
			//		if _, err := conn.Write(buf[:len]); err != nil {
			//			fmt.Println("write back buf err, ", err)
			//			continue
			//		}
			//	}
			//}()
		}
	}()

}

// 停止服务器
func (s *Server) Stop() {
	// TODO 将一些服务器的资源, 状态或者一些已经开辟的连接信息 进行停止或者回收
}

// 运行服务器
func (s *Server) Server() {
	s.Start()

	// TODO 做一些启动服务器之后的额外业务

	// 阻塞状态
	select {

	}
}

func (s *Server) AddRouter(router ziface.IRouter) {
	s.Router = router
	fmt.Println("Add Router Successful!")
}

// 初始化Server模块的方法
func NewServer(name string) ziface.IServer {
	s := &Server{
		//Name: name,
		Name: zutils.GlobalObject.Name,
		IPVersion: "tcp4",
		//IP: "0.0.0.0",
		//Port: 9000,
		IP: zutils.GlobalObject.Host,
		Port: zutils.GlobalObject.TcpPort,
		Router: nil,
	}
	return s
}